package org.ru.mse10.cvis.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.DuplicateKeyException;
import javax.ejb.ScheduleExpression;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

import org.ru.mse10.cvis.entity.search.CVSearchCriteria;
import org.ru.mse10.cvis.util.CommonUtil;

/**
 * The Class JobTimerService.
 */
@Stateless
public class JobTimerService extends EntityService {

	/** The timer service. */
	@Resource
	TimerService timerService;

	/*
	 * Callback method for the timers. Calls the corresponding Batch Job based
	 * on the JobInfo bounded to the timer
	 */

	/**
	 * Timeout.
	 * 
	 * @param timer
	 *            the timer
	 */
	@Timeout
	public void timeout(Timer timer) {
		System.out.println("###Timer <" + timer.getInfo() + "> timeout at "
				+ new Date());
		try {
			CommonUtil.lookupService(BatchJobTimer.class).executeJob(timer);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * Returns the Timer object based on the given JobTimer
	 */
	/**
	 * Gets the criteria.
	 * 
	 * @param searchCriteria
	 *            the search criteria
	 * @return the criteria
	 */
	private Timer getCriteria(CVSearchCriteria searchCriteria) {
		Collection<Timer> timers = timerService.getTimers();
		for (Timer t : timers) {
			if (searchCriteria.equals(t.getInfo())) {
				return t;
			}
		}
		return null;
	}

	/*
	 * Creates a timer based on the information in the JobTimer
	 */
	/**
	 * Creates the job.
	 * 
	 * @param searchCriteria
	 *            the search criteria
	 * @return the cV search criteria
	 * @throws Exception
	 *             the exception
	 */
	public CVSearchCriteria createJob(CVSearchCriteria searchCriteria)
			throws Exception {
		// Check for duplicates
		if (getCriteria(searchCriteria) != null) {
			throw new DuplicateKeyException("Job with the ID already exist!");
		}
		TimerConfig timerAConf = new TimerConfig(true, true);

		ScheduleExpression schedExp = new ScheduleExpression();
		// schedExp.start(searchCriteria.getStartDate());
		// schedExp.end(searchCriteria.getEndDate());
		schedExp.hour(searchCriteria.getHours());
		schedExp.minute(searchCriteria.getMinutes());
		Timer newTimer = timerService.createCalendarTimer(schedExp, timerAConf);
		searchCriteria.setNextTimeout(newTimer.getNextTimeout());

		return searchCriteria;
	}

	/*
	 * Returns a list of JobTimer for the active timers
	 */
	/**
	 * Gets the job timer list.
	 * 
	 * @return the job timer list
	 */
	public List<CVSearchCriteria> getJobTimerList() {
		ArrayList<CVSearchCriteria> jobList = new ArrayList<CVSearchCriteria>();
		Collection<Timer> timers = timerService.getTimers();
		for (Timer t : timers) {
			CVSearchCriteria searchCriteria = (CVSearchCriteria) t.getInfo();
			searchCriteria.setNextTimeout(t.getNextTimeout());
			jobList.add(searchCriteria);
		}
		return jobList;
	}

	/*
	 * Returns the updated JobTimer from the timer
	 */
	/**
	 * Gets the job info.
	 * 
	 * @param searchCriteria
	 *            the search criteria
	 * @return the job info
	 */
	public CVSearchCriteria getJobInfo(CVSearchCriteria searchCriteria) {
		Timer t = getCriteria(searchCriteria);
		if (t != null) {
			CVSearchCriteria j = (CVSearchCriteria) t.getInfo();
			j.setNextTimeout(t.getNextTimeout());
			return j;
		}
		return null;
	}

	/*
	 * Updates a timer with the given JobTimer
	 */
	/**
	 * Update job.
	 * 
	 * @param searchCriteria
	 *            the search criteria
	 * @return the cV search criteria
	 * @throws Exception
	 *             the exception
	 */
	public CVSearchCriteria updateJob(CVSearchCriteria searchCriteria)
			throws Exception {
		Timer t = getCriteria(searchCriteria);
		if (t != null) {
			t.cancel();
			return createJob(searchCriteria);
		}
		return null;
	}

	/*
	 * Remove a timer with the given JobTimer
	 */
	/**
	 * Delete job.
	 * 
	 * @param searchCriteria
	 *            the search criteria
	 */
	public void deleteJob(CVSearchCriteria searchCriteria) {
		Timer t = getCriteria(searchCriteria);
		if (t != null) {
			t.cancel();
		}
	}
}
